﻿/*********************************************************************
 * \file   exchange.hpp
 * \brief  交易所：用做数据中心，提供数据源、数据处理等服务
 *          如果明确的只是在程序内部交换数据，完全可以直接使用回调、信号槽等机制
 *          之所以搞这么一个集中式的数据交易中心，目的是可以通过 数据源ID 来统一地注册、注销数据接口
 *
 * \author boyun
 * \date   June 2023
 *********************************************************************/

#pragma once

#include <any>

// 使用 boost sinals2 库，发送消息
#include <boost/signals2/signal.hpp>
namespace sig2 = boost::signals2;

#include "http_rep.h"

namespace ex {
/**
 * 数据源抽象接口
 */
class source {
public:
    explicit source()
        : m_id(-1)
        , m_type(-1) {}
    virtual ~source() {}

    int  id() { return m_id; }
    void id(int id) { m_id = id; }
    int  type() { return m_type; }
    void type(int type) { m_type = type; }

public:
    // 信号：数据源打开
    sig2::signal<void()> on_open;
    // 信号：数据源关闭
    sig2::signal<void()> on_close;
    // 信号：有数据到达
    sig2::signal<void(std::any& data)> on_data;

private:
    int m_id;     // ID 唯一标识
    int m_type;   // 数据源类型（通常一个数据源，只发出一种类型的数据）
};

/**
 * 监听者抽象接口
 */
class listener {
public:
    explicit listener() {}
    virtual ~listener() {}

    int  source_id() { return m_source_id; }
    void source_id(int id) { m_source_id = id; }

    virtual void on_ds_open()               = 0;
    virtual void on_ds_close()              = 0;
    virtual void on_ds_data(std::any& data) = 0;

    boost::signals2::connection& connection_on_open() { return m_connection_on_open; }
    boost::signals2::connection& connection_on_close() { return m_connection_on_close; }
    boost::signals2::connection& connection_on_data() { return m_connection_on_data; }

private:
    int m_source_id;   // 监听数据源的 ID

    boost::signals2::connection m_connection_on_open;
    boost::signals2::connection m_connection_on_close;
    boost::signals2::connection m_connection_on_data;
};

/**
 * 交易所，提供数据源、数据监听者的注册和管理功能
 */
class exchange {
public:
    explicit exchange()
        : m_next_id(0) {}
    virtual ~exchange() { close(); }

    // 关闭
    void close() {
        for (auto ds : m_map_sources)
            if (ds.second) {
                ds.second->on_open.disconnect_all_slots();
                ds.second->on_close.disconnect_all_slots();
                ds.second->on_data.disconnect_all_slots();
            }
        m_map_sources.clear();
    }

    // 注册数据源
    response_t<int> regist_source(std::shared_ptr<source> ds) {
        if (nullptr == ds)
            return (int)rep_code::DATA_SOURCE_IS_EMPTY;

        // ID
        int id = m_next_id++;

        // 本地记录
        m_map_sources[id] = ds;
        ds->id(id);

        // 发送消息：新数据源注册
        on_source_create(*(ds.get()));

        // 返回注册的 ID
        response_t<int> ret(0);
        ret.data(id);
        return ret;
    }

    // 注销数据源
    void unregist_source(std::shared_ptr<source> ds) {
        int id = ds->id();

        if (m_map_sources.contains(id)) {
            auto ds = m_map_sources.at(id);

            // 脱钩断链
            ds->on_open.disconnect_all_slots();
            ds->on_close.disconnect_all_slots();
            ds->on_data.disconnect_all_slots();

            // 发送消息：数据源注销
            on_source_destory(*(ds.get()));

            // 擦除销毁
            m_map_sources.erase(id);
        }
    }

    // 注册数据监听者
    erc regist_listener(int ds_id, std::shared_ptr<listener> l) {
        if (nullptr == l)
            return (int)rep_code::LISTENER_IS_EMPTY;

        if (!m_map_sources.contains(ds_id))
            return (int)rep_code::DATA_SOURCE_IS_EMPTY;

        // 数据源
        auto ds = m_map_sources.at(ds_id);

        // 连接数据源的信号
        l->connection_on_open()  = ds->on_open.connect(std::bind(&listener::on_ds_open, l.get()));
        l->connection_on_close() = ds->on_close.connect(std::bind(&listener::on_ds_close, l.get()));
        l->connection_on_data() =
            ds->on_data.connect(std::bind(&listener::on_ds_data, l.get(), std::placeholders::_1));

        // 记录数据源的 ID
        l->source_id(ds_id);

        return (int)rep_code::SUCCESS;
    }

    // 注销数据监听
    erc unregist_listener(int ds_id, std::shared_ptr<listener> l) {
        if (nullptr == l)
            return (int)rep_code::LISTENER_IS_EMPTY;

        if (!m_map_sources.contains(ds_id))
            return (int)rep_code::DATA_SOURCE_IS_EMPTY;

        // 数据源
        auto ds = m_map_sources.at(ds_id);

        // 连接数据源的信号
        ds->on_open.disconnect(l->connection_on_open());
        ds->on_close.disconnect(l->connection_on_close());
        ds->on_data.disconnect(l->connection_on_data());

        // 记录数据源的 ID
        l->source_id(-1);

        return (int)rep_code::SUCCESS;
    }

public:
    // 信号：有新的数据源注册
    sig2::signal<void(source&)> on_source_create;
    // 信号：有数据源注销
    sig2::signal<void(source&)> on_source_destory;

private:
    int                                    m_next_id;       // 用于自动分配 ID
    std::map<int, std::shared_ptr<source>> m_map_sources;   // 数据源
};
}   // namespace ex
